#include <iostream>
using namespace std;

//引用
//符号：&
//用于类型与变量名之间

//引用不允许空引用，其所代表的类型，就是&前面那个类型
//example 1：
int main()
{

    int a = 0;
    int& b = a;
    //b就和a指向同一块内存，b改变值，a也改变值
    cout<<&b<<endl;
    cout<<&a<<endl;
    return 0;
}

// //example2:
// //函数在使用引用传参的时候，使用引用传递参数，就可以改变原参数，
// //这个形式参数指向的也是原实参数的内存
// // void change(int& b)
// // {
// //     b += 10;
// //     return ;
// // }
// // int main()
// // {
// //     int a = 0;
// //     change(a);
// //     cout<<a<<endl;//输出a+10之后的值，说明a的值已经被改变
// //     return 0;
// // }

函数在返回引用类型时，引用类型必须不被销毁
例如静态，全局，堆上malloc的空间
int& A()
{
    int* a = (int*)malloc(sizeof(int)*1);
    *a = 10;
    return *a;
}
int& B()
{
    int a = 11;
    return a;
}

int main()
{
    cout<<A()<<endl;//输出10
    // cout<<B()<<endl;//这里实际就应该报错，程序崩溃，因为访问了一块未申请的内存。

    return 0 ;
}

// //引用的权限只能不得超越原变量的权限
// int main()
// {
//     int a = 0;
//     int& b = a;//true

//     const int c = 0;
//     // int& d = c;//这里就会报错
//     const int &d = c ;//这样才是正确的引用

//     int e = 10;
//     // double& f = e;//这里一样报错
//     const double& f = e;//改正后正常
//     //原因是隐式类型转换，和c类似，这里不是e值直接给f,是把e提升成一个double的临时值，拿给f引用
//     //因为这块内存是在常量区的，所以遵循权限一致，加const
//     cout<<&e<<endl;
//     cout<<&f<<endl;
//     cout<<f<<endl;
//     cout<<sizeof(f)<<endl;
//     return 0;
// }


// //其实，引用在底层就是用指针的方式来实现的，也就能理解上述的原因了
// //区别：有多级指针，无多级引用
// //     必须给引用初始化
// //     类型上引用是设定时的类型，但是指针就是指针类型
